package io.xccit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.xccit.clients.ICategoryClients;
import io.xccit.clients.ISearchClients;
import io.xccit.mapper.IProductMapper;
import io.xccit.mapper.IProductPictureMapper;
import io.xccit.pojo.param.ProductByCategoryParam;
import io.xccit.pojo.param.ProductHotsParam;
import io.xccit.pojo.param.ProductSearchParam;
import io.xccit.pojo.product.Product;
import io.xccit.pojo.product.ProductPicture;
import io.xccit.result.AjaxResult;
import io.xccit.service.IProductService;
import io.xccit.to.OrderToProduct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author CH_ywx
 * @date 2023-09-10
 * @description
 */
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<IProductMapper, Product> implements IProductService {

    @Autowired
    private ICategoryClients categoryClients;

    @Autowired
    private IProductMapper productMapper;

    @Autowired
    private IProductPictureMapper productPictureMapper;

    @Autowired
    private ISearchClients searchClients;

    /**
     * 获取热门商品 每页最多七条数据
     *
     * @param categoryName
     * @return
     */
    @Cacheable(value = "list.product",key = "#categoryName")
    @Override
    public AjaxResult promo(String categoryName) {
        AjaxResult ajaxResult = categoryClients.selectByName(categoryName);
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String s = objectMapper.writeValueAsString(ajaxResult);
            log.info(s);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        //TODO 失败返回
//        if (ajaxResult.getCode() == AjaxMessageEnum.FAIL.getCode()){
//            return ajaxResult;
//        }
        //TODO 成功返回
        /**
         * 注意:feign调用之后返回的数据是一串JSON,Java会解析为LinkedHashMap对象,此处处理ajaxResult.getData()需要格外注意
         * 如果直接强转成Category获取其id,会造成类型转换异常
         * TODO错误示例: Category category = (Category) ajaxResult.getData();
         */
        LinkedHashMap<String,Object> linkedHashMap = (LinkedHashMap<String, Object>) ajaxResult.getData();
        Integer categoryId = (Integer) linkedHashMap.get("category_id");
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        //TODO 根据商品销量倒序排序 首页展示取前七条数据
        wrapper.eq(Product::getCategoryId,categoryId).orderByDesc(Product::getProductSales);
        Page<Product> productPage = new Page<>(1, 7);
        productPage = productMapper.selectPage(productPage, wrapper);
        //TODO:前端规则,只需要数据,不需要其他属性,getRecords()
        return AjaxResult.success(productPage.getRecords());
    }

    /**
     * @param productHotsParam
     * @return
     */
    @Cacheable(value = "list.product",key = "#productHotsParam.categoryName")
    @Override
    public AjaxResult hotsProduct(ProductHotsParam productHotsParam) {
        AjaxResult ajaxResult = categoryClients.hotsCategory(productHotsParam);
        if (ajaxResult.getCode() != 200){
            return AjaxResult.fail("查询失败");
        }
        //热门商品类别ID集合
        List<Object> ids = (List<Object>)ajaxResult.getData();
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Product::getCategoryId,ids).orderByDesc(Product::getProductSales);
        IPage<Product> productPage = new Page<>(1, 7);
        productPage = productMapper.selectPage(productPage,wrapper);
        return AjaxResult.success(productPage.getRecords());
    }

    /**
     * @return
     */
    @Cacheable(value = "list.category",key = "#root.methodName")
    @Override
    public AjaxResult categoryList() {
        //远程调用传回的category
        AjaxResult ajaxResult = categoryClients.list();
        return ajaxResult;
    }

    /**
     * @param productByCategoryParam
     * @return
     */
    @Cacheable(value = "list.product",key = "#productByCategoryParam.categoryID+'-'+#productByCategoryParam.currentPage+'-'+#productByCategoryParam.pageSize")
    @Override
    public AjaxResult selectProductByCategory(ProductByCategoryParam productByCategoryParam) {
        List<Integer> categoryID = productByCategoryParam.getCategoryID();
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        if (!categoryID.isEmpty()){
            wrapper.in("category_id",categoryID);
        }else {
            //集合为空,返回所有商品供全部列表显示
            IPage<Product> productPage = new Page<>(productByCategoryParam.getCurrentPage(), productByCategoryParam.getPageSize());
            productPage = productMapper.selectPage(productPage,null);
            return AjaxResult.success(productPage);
        }
        IPage<Product> productPage = new Page<>(productByCategoryParam.getCurrentPage(), productByCategoryParam.getPageSize());
        productPage = productMapper.selectPage(productPage,wrapper);
        return AjaxResult.success(productPage);
    }

    /**
     * @param productId
     * @return
     */
    @Cacheable(value = "list.product",key = "#productId")
    @Override
    public AjaxResult detail(Integer productId) {
        Product product = productMapper.selectById(productId);
        return AjaxResult.success(product);
    }

    /**
     * @param productId
     * @return
     */
    @Cacheable(value = "picture",key = "#productId")
    @Override
    public AjaxResult pictures(Integer productId) {
        LambdaQueryWrapper<ProductPicture> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductPicture::getProductId,productId);
        List<ProductPicture> productPictures = productPictureMapper.selectList(wrapper);
        return AjaxResult.success(productPictures);
    }

    /**
     * 搜索商品,使用关键字
     *
     * @param productSearchParam
     * @return
     */
    @Override
    public AjaxResult searchProduct(ProductSearchParam productSearchParam) {
        AjaxResult ajaxResult = searchClients.searchProduct(productSearchParam);
        log.info(ajaxResult.toString());
        return ajaxResult;
    }

    /**
     * 根据商品ID集合获取商品
     *
     * @param productIds
     * @return
     */
    @Cacheable(value = "list.product",key = "#productIds")
    @Override
    public AjaxResult getProductByIds(List<Integer> productIds) {
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Product::getProductId,productIds);
        List<Product> products = productMapper.selectList(wrapper);
        return AjaxResult.success(products);
    }

    /**
     * 获取购物车中的商品信息
     *
     * @param productIds 商品ID集合
     * @return
     */
    @Override
    public List<Product> cartProductList(List<Integer> productIds) {
        List<Product> products = productMapper.selectCartProductList(productIds);
        return products;
    }

    /**
     * 根据MQ消息的参数更新商品库存,增加销量
     *
     * @param orderToProducts
     */
    @Override
    public void updateProductNum(List<OrderToProduct> orderToProducts) {
        //TODO 转Map,以商品ID为key
        Map<Integer, OrderToProduct> productMap = orderToProducts.stream().collect(Collectors.toMap(OrderToProduct::getProductId, t -> t));
        //TODO 商品ID集合
        Set<Integer> productIds = productMap.keySet();
        //TODO 根据ID查询数据库中对应商品集合
        List<Product> products = productMapper.selectBatchIds(productIds);
        //TODO 遍历商品数据,对原有属性做更新
        for (Product product : products) {
            //TODO 查询消息订单中对应商品的下单数量
            Integer num = productMap.get(product.getProductId()).getNum();
            //TODO 对商品原有属性做更新
            product.setProductNum(product.getProductNum() - num);
            product.setProductSales(product.getProductSales() + num);
        }
        //TODO 数据库批量更新数据
        updateBatchById(products);
    }

    /**
     * 获取全部商品,使用远程调用异步操作同步至es
     *
     * @return
     */
    @Cacheable(value = "list.category" ,key = "#root.methodName" ,cacheManager = "cacheManagerDay")
    @Override
    public List<Product> productList() {
        return productMapper.selectList(null);
    }

}
